package com.fooddiary.service.impl;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.fooddiary.model.Eating;
import com.fooddiary.model.EatingType;
import com.fooddiary.model.Model;
import com.fooddiary.service.IEatingService;
import com.fooddiary.util.AppConstants;
import com.fooddiary.util.AppException;
import com.fooddiary.web.form.EatingForm;
import com.fooddiary.web.form.EatingTypeForm;

/**
 * 
 * @author Created by andrey.kuznetsov <br>
 * @author Last modified by $Author$ <br>
 * @author Last modified on $Date$ at revision $Revision$ <br>
 */
@Service
public class EatingService extends AbstractService implements IEatingService{

	private final Short OVERWEIGHT = 1;
	
	@Override
	@Transactional(readOnly=true)
	public EatingForm initEatingForm(Integer p_id, Integer p_weightId) throws AppException {
		EatingForm eatingForm = null;
		if(p_id == null || p_weightId == null){
			throw new AppException( messageSource.getMessage("message.error.common" , null, null ) );
		}
		Eating eating = (Eating) baseDao.getById( Eating.class, p_id );
		if(eating == null){
			throw new AppException( 
					messageSource.getMessage( "message.error.eating.not.found.by.id", new Object[]{p_id} , null ) );
		}
		eatingForm = new EatingForm();
		eatingForm.setId( p_id );
		eatingForm.setEnabled( AppConstants.ENTITY_STATE_ENABLED );
		eatingForm.setEatingTypeId( eating.getEatingType().getId() );
		eatingForm.setEatingType( new EatingTypeForm(eating.getEatingType()) );
		eatingForm.setTime( eating.getTime() );
		eatingForm.setFood( eating.getFood() );
		eatingForm.setOverweight( OVERWEIGHT.equals( eating.getOverweight() ) ? true : false );
		eatingForm.setWeightId( p_weightId );
		return eatingForm;
	}
	
	@Override
	@Transactional(readOnly=false)
	public EatingForm saveEatingForm(Model p_model, EatingForm p_eatingForm) throws AppException {
		checkModel( p_model );
		if(p_eatingForm == null){
			throw new AppException( messageSource.getMessage("message.error.common" , null, null ) );
		}
		validateEatingForm(p_eatingForm);
		Eating eating = (Eating) baseDao.getById( Eating.class, p_eatingForm.getId() );
		if(eating == null){
			p_eatingForm.getErrors().add( 
					messageSource.getMessage( "message.error.eating.not.found.by.id", new Object[]{p_eatingForm.getId()} , null ) );
		}
		EatingType eatingType = (EatingType) baseDao.getById( EatingType.class, p_eatingForm.getEatingTypeId() );
		if(eatingType == null){
			p_eatingForm.getErrors().add( 
					messageSource.getMessage( "message.error.eatingtype.not.found.by.id", new Object[]{p_eatingForm.getEatingTypeId()} , null ) );
		}
		if(CollectionUtils.isNotEmpty( p_eatingForm.getErrors() )){
			return p_eatingForm;
		}
		eating.setEatingType( eatingType );
		eating.setTime( p_eatingForm.getTime() );
		eating.setFood( p_eatingForm.getFood() );
		eating.setOverweight( p_eatingForm.getOverweight() ? OVERWEIGHT : 0 );
		baseDao.saveOrUpdate( eating );
		return p_eatingForm;
	}
	
	@Override
	@Transactional(readOnly=true)
	public List<EatingTypeForm> fillEatingTypesList(){
		List<EatingTypeForm> eatingTypeForms = new ArrayList<EatingTypeForm>();
		List<EatingType> eatingTypes = baseDao.getEnabledEntities( EatingType.class );
		if(CollectionUtils.isNotEmpty( eatingTypes )){
			for(EatingType eatingType: eatingTypes){
				eatingTypeForms.add( new EatingTypeForm( eatingType ) );
			}
		}
		return eatingTypeForms;
	}
	
	/**
	 * Validates EatingForm <br>
	 * @param p_eatingForm - {@link EatingForm}
	 */
	private void validateEatingForm(EatingForm p_eatingForm){
		String time = p_eatingForm.getTime().trim();
		try {
			applicationUtils.parseDateHHMMToLong( time );
		} catch ( ParseException err ) {
			p_eatingForm.getErrors().add( messageSource.getMessage( "message.error.eating.time.invalid", null, null ) );
		}
		
		String food = p_eatingForm.getFood().trim();
		if(StringUtils.length( food ) > AppConstants.FOOD_DESCRIPTION_LENGTH){
			p_eatingForm.getErrors().add( messageSource.getMessage("message.error.eating.food.length" , new Object[]{AppConstants.FOOD_DESCRIPTION_LENGTH}, null  ) );
		}
		p_eatingForm.setFood( food );
	}
}
